package nccloud.web.workflow.approvalcenter.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import itf.approvecenter.util.DataExchangeBean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import nc.bs.logging.Logger;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.wfengine.engine.ActivityInstance;
import nc.itf.pub.workflowqry.IFlowInstanceQuery;
import nc.itf.uap.pf.IPFWorkflowQry;
import nc.itf.uap.pf.IWorkflowDefine;
import nc.itf.uap.pf.IWorkflowMachine;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.pub.workflowqry.FlowHistoryQryResult;
import nc.vo.uap.wfmonitor.ProcessRouteRes;
import nc.vo.wfengine.core.activity.Activity;
import nc.vo.wfengine.core.activity.GenericActivityEx;
import nc.vo.wfengine.core.parser.XPDLParserException;
import nc.vo.wfengine.core.transition.BasicTransitionEx;
import nc.vo.wfengine.core.workflow.BasicWorkflowProcess;
import nc.vo.wfengine.definition.ActivityTypeEnum;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wfengine.pub.WFTask;
import nc.vo.wfengine.pub.WfTaskOrInstanceStatus;
import nc.vo.wfengine.pub.WfTaskType;
import nccloud.base.exception.ExceptionUtils;
import nccloud.baseapp.core.log.NCCForUAPLogger;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.mob.action.itf.IMobileAction;
import nccloud.framework.mob.container.IMobRequest;
import nccloud.framework.mob.container.MobClientInfo;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.container.SessionContext;
import nccloud.itf.uap.pf.NCCWorkFlowService;
import nccloud.vo.pf.flowinstance.NCCFlowInstanceVO;
import nccloud.web.workflow.approve.util.NCCFlowUtils;
import nccloud.web.workflow.approve.util.NCCMsgContext;




public class ApproveRejectAction
  implements ICommonAction, IMobileAction
{
  public Object doAction(IRequest request) {
    String jsonStr = request.read();
    
    String cuserid = SessionContext.getInstance().getClientInfo().getUserid();
    return doApproveReject(jsonStr, cuserid, false);
  }


  
  public Object doAction(IMobRequest req) {
    String jsonStr = req.read();
    String cuserid = (new MobClientInfo()).getUserid();

    
    return doApproveReject(jsonStr, cuserid, true);
  }






  
  private static Map<String, Activity> findAfterActivity(Activity act) {
    Stack<Activity> findActs = new Stack<Activity>();
    Map<String, String> hasFind = new HashMap<String, String>();
    Map<String, Activity> afterActs = new HashMap<String, Activity>();
    findActs.push(act);
    while (!findActs.isEmpty()) {
      Activity a = (Activity)findActs.pop();
      hasFind.put(a.getId(), a.getId());
      Map transMap = a.getEfferentTransitions();
      Iterator ite = transMap.entrySet().iterator();
      while (ite.hasNext()) {
        Map.Entry next = (Map.Entry)ite.next();
        BasicTransitionEx tran = (BasicTransitionEx)next.getValue();
        if (tran == null) {
          continue;
        }
        Activity toAct = tran.getToActivity();
        
        if (!hasFind.containsKey(toAct.getId())) {
          findActs.push(toAct);
        }
        
        if (!afterActs.containsKey(toAct.getId())) {
          afterActs.put(toAct.getId(), toAct);
        }
      } 
    } 
    return afterActs;
  }




  
  private void IsCanRejectSSC(String reject_activity, String billId, String billType, WorkflownoteVO note) {
    NCCWorkFlowService nccWorkFlowService = (NCCWorkFlowService)ServiceLocator.find(NCCWorkFlowService.class);



    
    try {
      IFlowInstanceQuery iflowinstance = (IFlowInstanceQuery)ServiceLocator.find(IFlowInstanceQuery.class);

      
      NCCFlowInstanceVO[] instances = iflowinstance.findFlowInstancesByBillIdAndBillTypeAppendOrderByCondition(billId, billType);
      
      if (instances != null && instances.length > 0) {
        billId = instances[0].getBillversionpk();
      } else {
        ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes()
            .getStrByID("0020nccloud_0", "0ncc0020001-0433"));
      } 
      
      ProcessRouteRes processRoute = ((IWorkflowDefine)ServiceLocator.find(IWorkflowDefine.class)).queryProcessRoute(billId, billType, null, 
          Integer.valueOf(instances[0].getWorkflow_type()).intValue());
      
      ActivityInstance[] actInsAry = processRoute.getActivityInstance();




      
      Map<String, String> actRoutes = new HashMap<String, String>();

      
      List<String> actInfos = new ArrayList<String>();
      
      Map<String, Activity> afterShareActInfos = new HashMap<String, Activity>();

      
      boolean isAfterShareCenter = false;
      
      boolean isFirstExamAct = false;
      
      int sscReviewActExam = 0;


      
      for (ActivityInstance actIns : actInsAry) {
        
        if (actIns.getStatus() != 4) {



          
          Activity actObject = null;
          
          try {
            actObject = PfDataCache.getWorkflowProcess(instances[0].getProcessdefid()).findActivityByID(actIns.getActivityID());
          } catch (XPDLParserException e) {
            
            NCCForUAPLogger.error(e.getMessage(), e);
            ExceptionUtils.wrapException(e);
          } 

          
          if (actObject instanceof GenericActivityEx) {
            
            GenericActivityEx act = (GenericActivityEx)actObject;
            
            String actType = nccWorkFlowService.getActivityType(act, billType);
            
            if (StringUtils.isNotEmpty(actType)) {












              
              if (isAfterShareCenter) {
                afterShareActInfos.put(actObject.getId(), actObject);
              }
              
              if (actType.equals("sscFirstExam")) {
                isAfterShareCenter = true;
                if (actObject.getId().equals(reject_activity)) {
                  isFirstExamAct = true;
                }
                if (!afterShareActInfos.containsKey(actObject.getId())) {
                  afterShareActInfos.put(actObject.getId(), actObject);
                }
                
                actInfos.add(act.getId());



              
              }
              else if (actType.equals("sscReview")) {
                isAfterShareCenter = true;
                if (!afterShareActInfos.containsKey(actObject.getId())) {
                  afterShareActInfos.put(actObject.getId(), actObject);
                }
                sscReviewActExam = 1;



                
                actInfos.add(act.getId());

              
              }

            
            }
            else if (isAfterShareCenter) {
              if (!afterShareActInfos.containsKey(actObject.getId())) {
                afterShareActInfos.put(actObject.getId(), actObject);
              }
              
              actInfos.add(act.getId());
            } 
          } 
        } 
      } 


      
      if (actInfos.size() > 0);




















    
    }
    catch (BusinessException e1) {
      
      NCCForUAPLogger.error(e1.getMessage(), e1);
      ExceptionUtils.wrapException(e1);
    } 
  }








  
  private Object doApproveReject(String jsonStr, String cuserid, boolean isMobile) {
    DataExchangeBean bean = new DataExchangeBean();
    bean.setCode("200");
    
    String billType = "";
    String billId = "";
    String pk_checkflow = "";
    String reject_activity = "";
    String check_note = "";
    boolean isCanRejectActity = false;
    int workflowtype = WorkflowTypeEnum.Approveflow.getIntValue();
    
    String old_billId = "";
    
    NCCMsgContext nccMsg = new NCCMsgContext(jsonStr);
    
    JSONObject json2 = JSON.parseObject(jsonStr);
    
    boolean isTrack = false;
    if (json2.get("isTrack") != null) {
      isTrack = json2.getBoolean("isTrack").booleanValue();
    }
    
    Map<String, Object> msgInfoMap = nccMsg.getMsgINfoContext();

    
    String[] flowParameterArray = { "billtype", "billid", "pk_checkflow" };

    
    if (NCCFlowUtils.isFlowParameterArrayNull(flowParameterArray, msgInfoMap)) {
      return NCCFlowUtils.exchangeDataMsg(bean, "500", 
          NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0428"));
    }

    
    billType = msgInfoMap.get("billtype").toString();
    old_billId = msgInfoMap.get("billid").toString();
    billId = msgInfoMap.get("billid").toString();
    pk_checkflow = msgInfoMap.get("pk_checkflow").toString();
    
    NCCFlowUtils.checkIsExistMessage(billType, billId, cuserid);
    AggregatedValueObject billvo = null;
    IWorkflowMachine machine = (IWorkflowMachine)ServiceLocator.find(IWorkflowMachine.class);
    NCCWorkFlowService nccWorkFlowService = (NCCWorkFlowService)ServiceLocator.find(NCCWorkFlowService.class);
    
    try {
      if (!isMobile)
      {
        if (StringUtils.isNotBlank(pk_checkflow)) {
          String pk_group = nccWorkFlowService.getGroupByPKCheckFlow(pk_checkflow);
          if (StringUtils.isNotBlank(pk_group)) {
            SessionContext.getInstance().getClientInfo().setPk_group(pk_group);
          }
        } 
      }

      
      billvo = nccWorkFlowService.mobileAppUtilForQueryBillEntity(billType, billId);
    } catch (BusinessException e) {
      ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0430"));
    } 




    
    try {
      NCCFlowInstanceVO[] resultInstance = ((IFlowInstanceQuery)ServiceLocator.find(IFlowInstanceQuery.class)).findFlowInstancesByBillIdAndBillTypeAppendOrderByCondition(billId, billType);
      if (resultInstance == null || resultInstance.length == 0) {
        return null;
      }
      
      billId = resultInstance[0].getBillversionpk();
      workflowtype = Integer.valueOf(resultInstance[0].getWorkflow_type()).intValue();
    }
    catch (BusinessException e3) {
      
      ExceptionUtils.wrapException(e3);
    } 

    
    String rejecttype = "";
    if (msgInfoMap.get("rejecttype") != null && msgInfoMap.get("rejecttype").toString() != "") {
      rejecttype = msgInfoMap.get("rejecttype").toString();
    }
    
    if (msgInfoMap.get("pk_wf_task") != null) {
      reject_activity = String.valueOf(msgInfoMap.get("pk_wf_task"));
    } else {
      reject_activity = null;
    } 


    
    if (msgInfoMap.get("checknote") != null) {
      check_note = String.valueOf(msgInfoMap.get("checknote"));
    }

    
    if (StringUtils.isEmpty(check_note)) {

      
      if ("billmake".equals(rejecttype)) {
        check_note = PfChecknoteEnum.REJECT_FIRST.toTextWithoutDeault();
      } else {
        check_note = PfChecknoteEnum.REJECT.toTextWithoutDeault();
      } 
      
      if (StringUtils.isEmpty(check_note)) {
        ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0523"));
      }
    } 



    
    WorkflownoteVO note = null;
    
    try {
      note = nccWorkFlowService.checkWorkflowActions(billType, billId, pk_checkflow);
    } catch (BusinessException e2) {
      ExceptionUtils.wrapException(e2);
    } 
    if (note == null) {
      ExceptionUtils.wrapBusinessException("WorkflownoteVO is null");
    }
    
    if (note != null) {
      note.setTrack(isTrack);
    }
    
    FlowHistoryQryResult result = null;
    try {
      result = ((IPFWorkflowQry)ServiceLocator.find(IPFWorkflowQry.class)).queryFlowHistoryQryResult(billType, billId, workflowtype);
    }
    catch (BusinessException e) {
      
      ExceptionUtils.wrapException(e);
    } 
    if (StringUtils.isNotEmpty(reject_activity) && result != null) {
      
      ProcessRouteRes processRoute = result.getProcessRoute();

      
      if (processRoute != null && processRoute.getActivityInstance() != null && processRoute
        .getActivityInstance().length > 0)
      {
        for (ActivityInstance acinst : processRoute.getActivityInstance()) {
          
          if (acinst.getStatus() == WfTaskOrInstanceStatus.Finished.getIntValue() && reject_activity
            .equals(acinst.getActivityID())) {
            isCanRejectActity = true;
          }
        } 
      }

      
      if (processRoute != null && processRoute.getSubProcessRoute() != null && processRoute
        .getSubProcessRoute().length > 0)
      {
        for (ProcessRouteRes prte : processRoute.getSubProcessRoute()) {
          if (prte != null && prte.getActivityInstance() != null && prte.getActivityInstance().length > 0) {
            for (ActivityInstance acinst : prte.getActivityInstance()) {
              if (acinst.getStatus() == WfTaskOrInstanceStatus.Finished.getIntValue() && reject_activity
                .equals(acinst.getActivityID())) {
                isCanRejectActity = true;
              }
            } 
          }
        } 
      }
    } 
    if (!isCanRejectActity && 
      StringUtils.isNotEmpty(reject_activity)) {
      ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("pfworkflow", "ApproveFlowRejectPanel-000000"));
    }


    
    String submit2RejectTache = "";
    try {
      submit2RejectTache = msgInfoMap.get("submit2RejectTache").toString();
    } catch (Exception e) {
      Logger.error(e);
    } 
    
    WFTask currentTask = null;

    
    try {
      currentTask = machine.getWFTask(note.getPk_wf_task());

      
      if (submit2RejectTache.equals("Y")) {
        note.getTaskInfo().getTask().setSubmit2RjectTache(true);
      }


      
      note.getTaskInfo().getTask().setTaskType(WfTaskType.Backward.getIntValue());
      
      NCCFlowUtils.checkIsCopySend(note, JSON.parseObject(jsonStr));
      if ("before".equals(rejecttype)) {
        
        boolean isSubflow = false;
        
        List<Activity> activitys = new ArrayList<Activity>();
        
        ProcessRouteRes processRoute = ((IWorkflowDefine)ServiceLocator.find(IWorkflowDefine.class)).queryProcessRoute(billId, billType, null, note
            .getWorkflow_type().intValue());
        ActivityInstance[] actInsAry = processRoute.getActivityInstance();


        
        BasicWorkflowProcess basicwfp = null;
        try {
          basicwfp = PfDataCache.getWorkflowProcess(currentTask.getWfProcessDefPK());
        } catch (XPDLParserException e) {
          ExceptionUtils.wrapException(e);
        } 
        if (note.getWorkflow_type().intValue() == 2 || note.getWorkflow_type().intValue() == 4) {
          
          for (ActivityInstance actins : actInsAry) {
            
            if (actins.getStatus() != 4 && actins.getStatus() != 0)
            {

              
              if (basicwfp.findActivityByID(actins.getActivityID())
                .getActivityType() != ActivityTypeEnum.Route.getIntValue() && basicwfp
                .findActivityByID(actins.getActivityID())
                .getActivityType() != ActivityTypeEnum.Auto.getIntValue())
              {

                
                if (actins.getActivityID()
                  .equals(basicwfp.findActivityByID(currentTask.getActivityID()).getId())) {
                  break;
                }

                
                activitys.add(basicwfp.findActivityByID(actins.getActivityID()));
              }
            
            }
          } 
        } else {
          
          isSubflow = true;
          List<Activity> list = basicwfp.getActivities();
          
          for (Activity act : list) {
            
            if (act.getActivityType() == ActivityTypeEnum.Route.getIntValue() || act
              .getActivityType() == ActivityTypeEnum.Auto.getIntValue()) {
              continue;
            }
            if (act.getId().equals(basicwfp.findActivityByID(currentTask.getActivityID()).getId())) {
              break;
            }

            
            activitys.add(act);
          } 
        } 




        
        if (isSubflow && activitys.size() == 0) {
          ExceptionUtils.wrapBusinessException(
              NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0432"));
        } else {
          note.getTaskInfo().getTask().setJumpToActivity(((Activity)activitys.get(activitys.size() - 1)).getId());
        } 
        
        IsCanRejectSSC(((Activity)activitys.get(activitys.size() - 1)).getId(), old_billId, billType, note);
      }
      else if ("billmake".equals(rejecttype)) {


        
        IFlowInstanceQuery iflowinstance = (IFlowInstanceQuery)ServiceLocator.find(IFlowInstanceQuery.class);
        
        NCCFlowInstanceVO[] instances = iflowinstance.findFlowInstancesByBillIdAndBillType(billId, billType);
        
        note.getTaskInfo().getTask().setBackToFirstActivity(true);
        
        if (instances == null || instances.length == 0) {
          ExceptionUtils.wrapBusinessException(
              NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0433"));
        } else {

          
          try {
            BasicWorkflowProcess basicWorkflowProcess = PfDataCache.getWorkflowProcess(instances[0].getProcessdefid());
            Activity startActivity = basicWorkflowProcess.findStartActivity();
            note.getTaskInfo().getTask().setJumpToActivity(startActivity.getId());
            IsCanRejectSSC(startActivity.getId(), old_billId, billType, note);
          } catch (XPDLParserException e) {
            ExceptionUtils.wrapException(e);
          }
        
        } 
      } else if (reject_activity == null || "".equals(reject_activity)) {


        
        note.getTaskInfo().getTask().setJumpToActivity(null);
        
        note.getTaskInfo().getTask().setBackToFirstActivity(true);
        
        IsCanRejectSSC(reject_activity, old_billId, billType, note);
      } else {
        
        int workflow_type = note.getWorkflow_type().intValue();
        String subflow = "";


        
        try {
          ProcessRouteRes processRoute = ((IWorkflowDefine)ServiceLocator.find(IWorkflowDefine.class)).queryProcessRoute(billId, billType, null, workflow_type);
          
          ActivityInstance[] actInsAry = processRoute.getActivityInstance();




          
          Map<String, String> actRoutes = new HashMap<String, String>();

          
          List<String> actInfos = new ArrayList<String>();
          
          Map<String, Activity> afterShareActInfos = new HashMap<String, Activity>();

          
          boolean isAfterShareCenter = false;
          
          int sscReviewActExam = 0;
          
          boolean isFirstExamAct = false;
          
          if (actInsAry != null && actInsAry.length > 0)
          {
            for (ActivityInstance actIns : actInsAry) {

              
              if (actIns.getStatus() != 4) {


                
                Activity actObject = null;


                
                try {
                  actObject = PfDataCache.getWorkflowProcess(note.getTaskInfo().getTask().getWfProcessDefPK()).findActivityByID(actIns.getActivityID());
                } catch (XPDLParserException e) {
                  NCCForUAPLogger.error(e.getMessage(), e);
                  ExceptionUtils.wrapException(e);
                } 


                
                if (actObject instanceof GenericActivityEx) {
                  
                  GenericActivityEx act = (GenericActivityEx)actObject;
                  
                  String actType = nccWorkFlowService.getActivityType(act, billType);
                  
                  if (StringUtils.isNotEmpty(actType)) {












                    
                    if (isAfterShareCenter) {
                      afterShareActInfos.put(actObject.getId(), actObject);
                    }
                    
                    if (actType.equals("sscFirstExam")) {
                      isAfterShareCenter = true;



                      
                      if (actObject.getId().equals(reject_activity)) {
                        isFirstExamAct = true;
                      }
                      if (!afterShareActInfos.containsKey(actObject.getId())) {
                        afterShareActInfos.put(actObject.getId(), actObject);
                      }
                      
                      actInfos.add(act.getId());



                    
                    }
                    else if (actType.equals("sscReview")) {
                      isAfterShareCenter = true;
                      if (!afterShareActInfos.containsKey(actObject.getId())) {
                        afterShareActInfos.put(actObject.getId(), actObject);
                      }
                      sscReviewActExam = 1;



                      
                      actInfos.add(act.getId());

                    
                    }

                  
                  }
                  else if (isAfterShareCenter) {
                    if (!afterShareActInfos.containsKey(actObject.getId())) {
                      afterShareActInfos.put(actObject.getId(), actObject);
                    }
                    
                    actInfos.add(act.getId());
                  } 
                } 
              } 
            } 
          }


          
          if (actInfos.size() > 0)
          {
            if (!afterShareActInfos.containsKey(reject_activity)) {
              ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes()
                  .getStrByID("0020nccloud_0", "0ncc0020001-0434"));
            }




            
            if (!isFirstExamAct || sscReviewActExam == 0);

          
          }


        
        }
        catch (BusinessException e1) {
          
          NCCForUAPLogger.error(e1.getMessage(), e1);
          ExceptionUtils.wrapException(e1);
        } 


        
        note.getTaskInfo().getTask().setBackToFirstActivity(false);





        
        note.getTaskInfo().getTask().setJumpToActivity(reject_activity);
      } 
      note.setApproveresult("R");
      if (StringUtils.isEmpty(check_note)) {
        check_note = NCCFlowUtils.getIndividualCheckNote(PfChecknoteEnum.REJECT, cuserid);
        note.setChecknote(check_note);
      } else {
        note.setChecknote(check_note);
      } 
      
      note.getTaskInfo().getTask().setTaskType(WfTaskType.Backward.getIntValue());
    }
    catch (BusinessException e) {
      
      ExceptionUtils.wrapException(e);
    }
    catch (Exception e) {
      
      ExceptionUtils.wrapException(e);
    } 

    
    try {
      NCCFlowUtils.handleAttrfiles(json2, note);























      
      if (note.getWorkflow_type().intValue() == WorkflowTypeEnum.Approveflow.getIntValue() || note
        .getWorkflow_type().intValue() == WorkflowTypeEnum.SubApproveflow.getIntValue()) {
        
        ApproveOrSignalActionUtil.processAction("APPROVE", billType, note, billvo, null, null, null);
      } else {
        
        ApproveOrSignalActionUtil.processAction("SIGNAL", billType, note, billvo, null, null, null);
      }
    
    } catch (Exception ex) {
      
      ExceptionUtils.wrapException(ex);
    } 
    
    return bean;
  }
}